use std::{
    collections::HashMap,
    fs::File,
    io::{self, BufRead, BufReader},
};

#[derive(Clone, Debug, Default)]
struct WadeGiles {
    words: Vec<(String, String)>,
    chars: HashMap<char, String>,
}

fn title_upper(word: &str) -> String {
    let mut chars = word.chars();
    if let Some(c) = chars.next() {
        c.to_uppercase().to_string() + chars.as_str()
    } else {
        String::new()
    }
}

impl WadeGiles {
    fn new() -> io::Result<Self> {
        let mut wg = WadeGiles::default();
        wg.load_file("c_py.data", true)?;
        wg.load_file("w_py.data", false)?;
        Ok(wg)
    }

    fn init_c(&mut self, k: &str, v: &str) {
        self.chars.insert(k.chars().next().unwrap(), v.to_string());
    }

    fn init_w(&mut self, k: &str, v: &str) {
        self.words.push((k.to_string(), v.to_string()));
    }

    fn load_file(&mut self, file_name: &str, is_c: bool) -> io::Result<()> {
        let file = File::open(file_name)?;
        let mut reader = BufReader::new(file);
        let mut data = String::new();
        loop {
            data.clear();
            let bytes = reader.read_line(&mut data)?;
            if bytes == 0 {
                break;
            }
            if let Some((k, v)) = data.trim().split_once(',') {
                if is_c {
                    self.init_c(k, v);
                } else {
                    self.init_w(k, v);
                }
            }
        }
        Ok(())
    }
    fn convert(&self, input: &str) -> String {
        let mut words = Vec::new();
        // todo 基于words分词

        for (k, v) in &self.words {
            if let Some(index) = input.find(k) {
                let mut cross = false;
                for (i, len, _) in &words {
                    if (index >= *i && index <= *i + len) || (*i >= index && *i <= index + k.len())
                    {
                        cross = true;
                        break;
                    }
                }
                if !cross {
                    words.push((index, k.len(), v));
                }
            }
        }
        let v_input = input.chars().collect::<Vec<char>>();
        let mut word_index = 0;
        let mut index = 0;
        let mut res = Vec::new();
        while index < v_input.len() {
            if words.len() > word_index {
                let (i, len, w) = words[word_index];
                if i == index {
                    if res.is_empty() {
                        res.push(title_upper(w));
                    } else {
                        res.push(w.clone());
                    }
                    index += len;
                    word_index += 1;
                }
                continue;
            }
            if let Some(v) = self.chars.get(&v_input[index]) {
                if res.is_empty() {
                    res.push(title_upper(v));
                } else {
                    res.push(v.clone());
                }
            }
            index += 1;
        }
        res.join(" ")
    }
}

pub fn converter(input: &str) -> String {
    let wg = WadeGiles::new().unwrap();
    wg.convert(input)
}
